/*
    封装实现一个SqliteHelper类，提供简单的sqlite数据库操作接口，完成数据的基础增删改查操作。
        1. 创建/打开数据库文件
        2. 针对打开的数据库执行操作
            1. 表的操作
            2. 数据的操作
        3. 关闭数据库
*/
#include <iostream>
#include <string>
#include <vector>
#include <sqlite3.h>

class SqliteHelper {
public:
    // 定义SQLite回调函数类型，用于处理查询结果
    // 参数：
    //   - void*：传递给sqlite3_exec的用户数据
    //   - int：结果集中的列数
    //   - char**：每列的数据
    //   - char**：每列的名称
    typedef int(*SqliteCallback)(void*, int, char**, char**);

    // 构造函数：初始化数据库文件路径，句柄初始化为nullptr
    SqliteHelper(const std::string &dbfile) : _dbfile(dbfile), _handler(nullptr) {}
    
    // 打开或创建SQLite数据库
    // 参数：
    //   - safe_leve：SQLite打开标志，默认为SQLITE_OPEN_FULLMUTEX（多线程安全）
    // 返回值：成功返回true，失败返回false
    bool open(int safe_leve = SQLITE_OPEN_FULLMUTEX) {
        // 使用sqlite3_open_v2打开数据库，支持更多选项
        // 标志组合：
        //   - SQLITE_OPEN_READWRITE：读写模式
        //   - SQLITE_OPEN_CREATE：如果数据库不存在则创建
        //   - safe_leve：用户指定的安全级别（如多线程模式）
        int ret = sqlite3_open_v2(_dbfile.c_str(), &_handler, 
                                  SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | safe_leve, nullptr);
        if (ret != SQLITE_OK) {
            // 打开失败时输出错误信息
            std::cout << "创建/打开sqlite数据库失败: ";
            std::cout << sqlite3_errmsg(_handler) << std::endl;
            return false;
        }
        return true;
    }

    // 执行SQL语句（查询或非查询）
    // 参数：
    //   - sql：要执行的SQL语句
    //   - cb：查询结果的回调函数（查询时使用，非查询操作传nullptr）
    //   - arg：传递给回调函数的用户数据
    // 返回值：成功返回true，失败返回false
    bool exec(const std::string &sql, SqliteCallback cb, void *arg) {
        // 使用sqlite3_exec执行SQL语句
        // 参数：
        //   - _handler：数据库句柄
        //   - sql.c_str()：SQL语句字符串
        //   - cb：回调函数（用于处理查询结果）
        //   - arg：传递给回调函数的用户数据
        //   - nullptr：错误信息指针（此处不使用，直接通过返回值判断）
        int ret = sqlite3_exec(_handler, sql.c_str(), cb, arg, nullptr);
        if (ret != SQLITE_OK) {
            // 执行失败时输出错误信息
            std::cout << sql << std::endl;
            std::cout << "执行语句失败: ";
            std::cout << sqlite3_errmsg(_handler) << std::endl;
            return false;
        }
        return true;
    }

    // 关闭数据库连接
    void close() {
        // 使用sqlite3_close_v2关闭数据库，支持更安全的资源释放
        // 检查句柄是否有效，避免重复关闭或关闭空句柄
        if (_handler) sqlite3_close_v2(_handler);
    }

private:
    std::string _dbfile;  // 数据库文件路径
    sqlite3 *_handler;    // SQLite数据库句柄
};    